/*
 * Copyright (C) 2012-2013  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.remote.rsa.message.impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.rmi.RemoteException;

import nemos.remote.rsa.internal.RsaMessage;
import nemos.remote.rsa.message.data.InvocationMessage;
import nemos.remote.rsa.message.data.ResponseMessage;
import nemos.remote.rsa.message.transport.ITransport;
import nemos.util.i18n.NemosTranslator;

import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceException;
import org.osgi.service.remoteserviceadmin.EndpointDescription;

/**
 * Stub : The stub class for remote services.
 * 
 * @author Romain DUBOIS
 */
public class Stub implements InvocationHandler {

    /** The target endpoint */
    private final EndpointDescription mEndpoint;
    /** The service which transports messages */
    private final ITransport mTransport;
    /** The calling bundle */
    private final Bundle mBundle;
    /** The translator */
    private final NemosTranslator mTranslator;

    /**
     * Constructor
     * 
     * @param pEndpoint
     *            The target endpoint
     * @param pTransport
     *            The service which transports messages
     * @param pBundle
     *            The calling bundle
     */
    public Stub(final EndpointDescription pEndpoint, final ITransport pTransport,
            final Bundle pBundle) {
        super();
        mEndpoint = pEndpoint;
        mTransport = pTransport;
        mBundle = pBundle;
        mTranslator = new NemosTranslator(FrameworkUtil.getBundle(Stub.class));
    }

    /**
     * {@inheritDoc}
     * 
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     *      java.lang.reflect.Method, java.lang.Object[])
     */
    @Override
    public Object invoke(@SuppressWarnings("unused") final Object pProxy, final Method pMethod,
            final Object[] pArgs) throws Throwable {

        ResponseMessage lResponse = null;
        RemoteException lRemoteException = null;

        // Send call message
        try {
            lResponse = mTransport.call(new InvocationMessage(mEndpoint, pMethod, pArgs));
            lRemoteException = lResponse.getRemoteException();
        } catch (final RemoteException e) {
            lRemoteException = e;
        }

        // Check error
        if (lRemoteException != null || lResponse == null) {
            final String lText = mTranslator.getMessage(RsaMessage.REMOTE_CALL_FAILED,
                    mEndpoint.getId());
            throw new ServiceException(lText, ServiceException.REMOTE, lRemoteException);
        }

        // Return of throw invocation exception
        return lResponse.getResult(mBundle);
    }

    /**
     * Close the stub.
     */
    public void close() {
        mTranslator.close();
    }
}
